package com.zhxy.gis;

import java.io.IOException;
import java.io.Serializable;
import java.util.concurrent.ExecutorService;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.zhxy.util.bean.EventProvider;

public class BaiduCoordinateEncryption implements CoordinateEncryption {

	private EventProvider<CoordinateEncryptionListener> event = new EventProvider<CoordinateEncryptionListener>();

	private int connectionCount = 1;
	
	private long waitBy = 0;

	private ExecutorService executorService;

	private MultiThreadedHttpConnectionManager manager;
	
	private HttpClient client;

	public int getConnectionCount() {
		return connectionCount;
	}

	public void setConnectionCount(int connectionCount) {
		this.connectionCount = connectionCount;
	}

	public long getWaitBy() {
		return waitBy;
	}

	public void setWaitBy(long waitBy) {
		this.waitBy = waitBy;
	}

	public ExecutorService getExecutorService() {
		return executorService;
	}

	public void setExecutorService(ExecutorService executorService) {
		this.executorService = executorService;
	}

	public void init() {

		HttpConnectionManagerParams params = new HttpConnectionManagerParams();
		params.setMaxTotalConnections(connectionCount);
		params.setDefaultMaxConnectionsPerHost(connectionCount);

		manager = new MultiThreadedHttpConnectionManager();
		manager.setParams(params);
		
		client = new HttpClient(manager);
	}

	@Override
	public void addCoordinateEncryptionListener(
			CoordinateEncryptionListener listener) {
		event.addEventListener(listener);
	}

	@Override
	public void removeCoordinateEncryptionListener(
			CoordinateEncryptionListener listener) {
		event.removeEventListener(listener);
	}

	@Override
	public void encrypt(Location location, Object o) {
		
		final Location l = location;
		final Object o0 = o;
		
		executorService.execute(new Runnable() {
			
			@Override
			public void run() {
				try {
					Location n = doEncrypt(l);
					for (CoordinateEncryptionListener listener : event.toList()) {
						listener.complete(l, n, o0);
					}
					if (waitBy != 0)
						Thread.sleep(waitBy);
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (Exception e) {
					for (CoordinateEncryptionListener listener : event.toList()) {
						listener.error(l, o0);
					}
				}
			}
		});
	}

	protected Location doEncrypt(Location location) throws IOException {

		GetMethod method = new GetMethod(
				"http://api.map.baidu.com/ag/coord/convert");
		method.setQueryString("from=0&to=4&x=" + location.getLongitude()
				+ "&y=" + location.getLatitude());
		method.setRequestHeader("Connection", "keep-alive");
		//HttpClient client = new HttpClient(manager);
		int code = client.executeMethod(method);

		if (200 != code) {
			throw new IOException("当前状态码:" + code);
		}

		String body = method.getResponseBodyAsString();
		JsonObject json = (JsonObject) new JsonParser().parse(body);
		//int error = json.get("error").getAsInt();
		String x = json.get("x").getAsString();
		String y = json.get("y").getAsString();

		x = new String(Base64.decodeBase64(x));
		y = new String(Base64.decodeBase64(y));

		return new Location(Double.parseDouble(y), Double.parseDouble(x));

	}

}
